
#ifndef _SOURCES_H__
#define _SOURCES_H__

#if HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */

/* System Includes */
#if HAVE_TIME_H
#include <time.h>
#endif /* HAVE_TIME_H */

/* System Includes */
#if HAVE_MATH_H
#include <math.h>
#endif

#if HAVE_STDIO_H
#include <stdio.h> 
#endif /* HAVE_STDIO_H */

#if HAVE_STDLIB_H 
#include <stdlib.h>
#endif  /* HAVE_STDLIB_H */

#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */

#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif

#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif

#if HAVE_UNISTD_H
#include <unistd.h>
#endif  /* HAVE_UNISTD_H */

#if HAVE_CTYPE_H
#include <ctype.h>
#endif

/* Local Includes */
extern "C"{ 
#include "tokenizer.h"
#include "sources.h"
#include "cgdb.h"
#include "sys_util.h"
#include "cgdbrc.h"
}
#include "Window.h"
#include "Highlight_groups.h"
#include "Highlight.h"
#include "Logo.h"
/* ----------- */
/* Definitions */
/* ----------- */

/* Max length of a line */
#define MAX_LINE        4096
#define MAX_TITLE       40
#define SRC_WINDOW_NAME "Source"
#define QUEUE_SIZE      10

/* --------------- */
/* Data Structures */
/* --------------- */


class Sources: public Window
{
    /* --------------- */
    /* Data Structures */
    /* --------------- */
    public:
        struct buffer{
            int    length;                     /* Number of lines in buffer */
            char **tlines;                     /* Array containing file ( lines of text ) */
            char *cur_line;                    /* cur line may have unique color */
            char  *breakpts;                   /* Breakpoints */
            int    max_width;                  /* Width of longest line in file */
        };       
        struct list_node{
            char             *path;            /* Full path to source file */
            char             *lpath;           /* Relative path to source file */
            struct buffer     buf;             /* File buffer */
            struct buffer     orig_buf;        /* Original File buffer ( no color ) */
            int               sel_line;        /* Current line selected in viewer */
            int               sel_col;         /* Current column selected in viewer */
            int               exe_line;        /* Current line executing */
            int               sel_col_rbeg;    /* Current beg column matched in regex */
            int               sel_col_rend;    /* Current end column matched in regex */
            int               sel_rline;       /* Current line used by regex */
            enum tokenizer_language_support language; /* The language type of this file */
            time_t last_modification; /* timestamp of last modification */
            struct list_node *next;            /* Pointer to next link in list */
        };
        list_node* mList_head;       /* File list */    
        list_node* mCur;             /* Current node we're displaying */

        Sources();

        /* --------- */
        /* Functions */
        /* --------- */
        /* Add:  Add a file to the list of source files.
         * -----------
         *
         *   sview:  Source viewer object
         *   path:   Full path to the source file (this is considered to be a
         *           unique identifier -- no duplicate paths in the list!)
         *
         * Return Value:  Zero on success, non-zero on error.
         */
        int Add(const char *path);

        /* source_set_relative_path: Sets the path that gdb uses for breakpoints
         * -------------------------
         * 
         *   sview:  Source viewer object
         *   path:   Full path to the source file (this is considered to be a
         *           unique identifier -- no duplicate paths in the list!)
         *   lpath:  
         *
         * Return Value:  Zero on success, non-zero on error.
         */
        int Set_relative_path(const char *path, const char *lpath);

        /* source_del:  Remove a file from the list of source files.
         * -----------
         *
         *   sview:  Source viewer object
         *   path:   Full path to the source file to remove from the list.  If the
         *           file is buffered in memory, it'll be freed.
         *
         * Return Value:  Zero on success, non-zero on error.
         */ 
        int Del(const char *path);

        /* source_length:  Get the length of a source file.  If the source file hasn't
         * --------------  been buffered already, it will be loaded into memory.
         *
         *   sview:  Source viewer object
         *   path:   Full path to the source file
         *
         * Return Value:  Length of file on success, -1 on error.
         */
        int Length(const char *path);

        /* source_current_file: Get the name of the current file being displayed.
         * --------------------
         *
         *  path: The path to the current file being displayed.
         *  
         *  Return Value: NULL if no file is being displayed, otherwise a pointer to
         *                the current path of the file being displayed.
         */
        char* Current_file(char *path);

        /* source_display:  Display a portion of a file in a curses window.
         * ---------------
         *
         *   sview:  Source viewer object
         *   focus:  If the window should have focus
         *
         * Return Value:  Zero on success, non-zero on error.
         */
        virtual int Display(int focus);

        /* source_vscroll:  Change current position in source file.
         * --------------
         * 
         *   sview:   Source viewer object
         *   offset:  Plus or minus number of lines to move
         */
        void Vscroll(int offset);

        /* source_hscroll:  Scroll the source file right or left in the window.
         * ---------------
         *
         *   sview:   Source viewer object
         *   offset:  Plus or minus number of lines to move
         */
        void Hscroll(int offset);

        /* source_set_sel_line:  Set current user-selected line
         * --------------------
         *
         *   sview:  Source viewer object
         *   line:   Current line number
         *
         */
        void Set_sel_line(int line);

        /* source_set_exec_line:  Set currently executing line
         * ---------------
         *
         *   sview:  Source viewer object
         *   path:   Full path to the source file (may be NULL to leave unchanged)
         *   line:   Current line number (0 to leave unchanged)
         *
         * Return Value: Zero on success, non-zero on failure.
         *               5 -> file does not exist
         */
        int Set_exec_line(const char *path, int line);

        /* source_search_regex_init: Should be called before source_search_regex
         * -------------------------
         *   This function initializes sview before it can search for a regex
         *   It should be called every time a regex will be applied to sview before
         *   source_search_regex is called.
         *
         *   sview:  Source viewer object
         */
        void Search_regex_init();

        /* source_search_regex: Searches for regex in current file and displays line.
         * ---------------
         *
         *   sview:  Source viewer object
         *   regex:  The regular expression to search for
         *           If NULL, then no regex will be tried, but the state can still
         *           be put back to its old self!
         *   opt:    If 1, Then the search is temporary ( User has not hit enter )
         *           If 2, The search is perminant
         *
         *   direction: If 0 then forward, else reverse
         *   icase:     If 0 ignore case.
         *
         * Return Value: Zero on match, 
         *               -1 if sview->cur is NULL
         *               -2 if regex is NULL
         *               -3 if regcomp fails
         *               non-zero on failure.
         */
        int Search_regex(const char *regex, int opt,
                int direction, int icase);

        /* source_free:  Release the memory associated with a source viewer.
         * ------------
         *
         *   sview:  The source viewer to free.
         */
        void Free();

        /* ----------- */
        /* Breakpoints */
        /* ----------- */

        /* source_disable_break:  Disable a given breakpoint.
         * ---------------------
         *
         *   sview:  The source viewer object
         *   path:   Full path to the source file
         *   line:   Line number of breakpoint
         */
        void Disable_break(const char *path, int line);

        /* source_enable_break:  Enable a given breakpoint.
         * --------------------
         *
         *   sview:  The source viewer object
         *   path:   Full path to the source file
         *   line:   Line number of breakpoint
         */
        void Enable_break(const char *path, int line);

        /* source_clear_breaks:  Clear all breakpoints from all files.
         * --------------------
         *
         *   sview:  The source viewer object
         */
        void Clear_breaks();

        /**
         * Check's to see if the current source file has changed. If it has it loads
         * the new source file up.
         *
         * \param sview
         * The source viewer object
         *
         * \param path
         * The path to the file to reload into memory
         *
         * \param force
         * Force the file to be reloaded, even if autosourcereload option is off.
         *
         * \return
         * 0 on success or -1 on error
         */
        int Reload(const char *path, int force );

    private:

        /* --------------- */
        /* Private Functions */
        /* --------------- */

        /* verify_file_exists: Checks to see if a file exists
         * -------------------
         *
         * Return Value: 0 if does not exist, 1 if exists 
         */
        int Verify_file_exists(const char *path); 

        /* get_relative_node:  Returns a pointer to the node that matches the 
         * ------------------  given relative path.

         *   lpath:  Full path to source file
         *
         * Return Value:  Pointer to the matching node, or NULL if not found.
         */
        Sources::list_node* Get_relative_node(const char *lpath);

        /* get_node:  Returns a pointer to the node that matches the given path.
         * ---------

         *   path:  Full path to source file
         *
         * Return Value:  Pointer to the matching node, or NULL if not found.
         */
        Sources::list_node* Get_node(const char *path);


        /**
         * Get's the timestamp of a particular file.
         *
         * \param path
         * The path to the file to get the timestamp of
         *
         * \param timestamp
         * The timestamp of the file, or 0 on error.
         * 
         * \return
         * 0 on success, -1 on error.
         */
        int Get_timestamp(const char *path, time_t *timestamp );

        int Release_file_buffer(buffer *buf );

        /** 
         * Remove's the memory related to a file.
         *
         * \param node
         * The node who's file buffer data needs to be freed.
         *
         * \return
         * 0 on success, or -1 on error.
         */
        int Release_file_memory(list_node *node );

        /* load_file:  Loads the file in the list_node into its memory buffer.
         * ----------
         *
         *   node:  The list node to work on
         *
         * Return Value:  Zero on success, non-zero on error.
         */
        int Load_file(list_node *node);
        /* draw_current_line:  Draws the currently executing source line on the screen
         * ------------------  including the user-selected marker (arrow, highlight,
         *                     etc) indicating this is the executing line.
         *
         *   sview:  The current source viewer
         *   line:   The line number
         *   lwidth: The width of the line number, used to limit printing to the width
         *           of the screen.  Kinda ugly.
         */
        void Draw_current_line(int line, int lwidth);

};

#endif //_SOURCES_H__
